package com.lcc.generate.vue3;

import com.alibaba.druid.util.StringUtils;
import com.lcc.generate.Config;
import com.lcc.generate.StringBuilder2;
import com.lcc.generate.TableConfig;
import com.lcc.generate.util.FileUtils;
import com.lcc.generate.util.JDBCUtil;
import com.lcc.generate.util.MyField;

import java.io.*;
import java.util.*;

public class Vue3Util {

    private static String vuePath;

    private static String headerName;
    private static StringBuilder elFormExpandItems;
    private static StringBuilder elFormBaseItems;
    private static StringBuilder tableColumns;
    private static StringBuilder formRules;
    private static StringBuilder formParams;
    private static StringBuilder baseFormParams;
    private static StringBuilder expandFormParams;
    private static StringBuilder dictParams;
    private static StringBuilder watchParams;
    private static StringBuilder baseColumns;
    private static StringBuilder formItems;
    private static StringBuilder orderByInList;
    private static String api;
    private static String idName;		// 主键 驼峰
    private static String permission;		// 权限
    private static String generateVue3;		// 权限

    private static List<MyField> fields;
    private static String columnStart = "<!-- el-table-column-start -->";
    private static String columnEnd = "<!-- el-table-column-end -->";
    private static Config generateConfig;

    public static void generate(List<List<MyField>> fieldsArr, Config config) {
        System.out.println("----- 生成Vue3");
        generateConfig = config;
        for (int i = 0; i < fieldsArr.size(); i++) {
            vuePath = config.vuePath;
            if (!StringUtils.isEmpty(config.generateConfigs[i].generateVue3)
                    && ("v1".equals(config.generateConfigs[i].generateVue3) || "v2".equals(config.generateConfigs[i].generateVue3)))
            {
                // 处理 v1 v2
                createVue3(fieldsArr.get(i), config.generateConfigs[i]);
            }
        }
    }
    public static void createVue3(List<MyField> fieldArr, TableConfig config) {
        //初始化
        api = JDBCUtil.toHump(config.getTableName(generateConfig.ifNoPrefix));
        permission = config.getTableName(generateConfig.ifNoPrefix).replace("_", ":");
        String path = api.substring(0, 1).toLowerCase() + api.substring(1);
        String dv = JDBCUtil.toHump(config.getTableName(generateConfig.ifNoPrefix), true) + "DV";
        vuePath = vuePath + "/" + path;
        api = path + "Api";
        fields = fieldArr;
        headerName = config.tableComment;
        generateVue3 = config.generateVue3;
        idName = "";
        for (MyField field : fields) {
            if(field.column.equals(config.primaryKey)){
                idName = field.name;
            }
        }

        addFormItems();
        addTableColumns();
        addFormRules();
        addFormParams();
        addBaseFormParams();
        orderByInList();
        addDictParams();
        addBaseColumns();

        File vueRoot = new File(vuePath);
        if(!vueRoot.exists()){
            vueRoot.mkdirs();
        }
        File file = new File(vueRoot, "index.vue");
        if(!file.exists() || generateConfig.coverVueIndex){
            StringBuilder2 indexSB;
            if("v2".equals(config.generateVue3)){
                indexSB = FileUtils.getTempString("temp/vue3-v2/index.vue");
            }else {
                indexSB = FileUtils.getTempString("temp/vue3-v1/baseIndex.vue");
            }
            indexSB.replace("${headerName}", headerName)
                    .replace("${idName}", idName)
                    .replace("${uri}", config.requestMapping)
                    .replace("${dv}", dv);
            FileUtils.write(file, indexSB.toString());
            System.out.println("生成：" + path + "/index.vue");
        }

        if("v2".equals(config.generateVue3)) {
            createAllVue3(vueRoot, path, dv);
        }

        file = new File(vueRoot, "main.ts");
        if(!file.exists() || generateConfig.coverMainTs){
            StringBuilder2 typeSB = FileUtils.getTempString("temp/vue3-v2/main.ts");
            typeSB.replace("${dv}", dv)
                    .replace("${baseColumns}", baseColumns.toString())
                    .replace("${formItems}", formItems.toString());
            FileUtils.write(file, typeSB.toString());
            System.out.println("生成：" + path + "/main.ts");
        }

        StringBuilder2 baseSB = FileUtils.getTempString("temp/vue3-v2/base.ts");
        baseSB.replace("${baseFormParams}", baseFormParams.toString())
                .replace("${formRules}", formRules.toString())
                .replace("${dictParams}", dictParams.toString())
                .replace("${orderByInList}", orderByInList.toString())
                .replace("${api}", api)
                .replace("${permission}", permission)
                .replace("${idName}", idName)
                .replace("${baseColumns}", baseColumns.toString())
                .replace("${formItems}", formItems.toString())
                .replace("${tableColumns}", tableColumns.toString())
                ;
        file = new File(vueRoot, "base.ts");
        FileUtils.write(file, baseSB.toString());
        System.out.println("生成：" + path + "/base.ts");

//        StringBuilder formItemSB = FileUtils.getTempString("temp/formItem.vue");
//        String formItemString = formItemSB.toString()
//                .replace("${elFormItems}", elFormExpandItems + elFormBaseItems.toString());
//        file = new File(vueRoot, "formItem.vue");
//        FileUtils.write(file, formItemString);
//        System.out.println("生成：" + path + "/formItem.vue");
    }

    private static void createAllVue3(File vueRoot, String path,  String dv) {
        File file;
        StringBuilder2 addSB = FileUtils.getTempString("temp/vue3-v2/add.vue");
        addSB.replace("${dv}", dv);
        file = new File(vueRoot, "add.vue");
        if(!file.exists() || generateConfig.coverVueAdd){
            FileUtils.write(file, addSB.toString());
            System.out.println("生成：" + path + "/add.vue");
        }

        StringBuilder2 updateSB = FileUtils.getTempString("temp/vue3-v2/update.vue");
        updateSB.replace("${dv}", dv);
        file = new File(vueRoot, "update.vue");
        if(!file.exists() || generateConfig.coverVueUpdate){
            FileUtils.write(file, updateSB.toString());
            System.out.println("生成：" + path + "/update.vue");
        }

        StringBuilder2 infoSB = FileUtils.getTempString("temp/vue3-v2/info.vue");
        infoSB.replace("${dv}", dv);
        file = new File(vueRoot, "info.vue");
        if(!file.exists() || generateConfig.coverVueInfo){
            FileUtils.write(file, infoSB.toString());
            System.out.println("生成：" + path + "/info.vue");
        }
    }

    private static void addBaseColumns() {
        baseColumns = new StringBuilder();
        for (MyField field : fields) {
            if(field.isSkip) continue;
            Integer minWidth = null;
            baseColumns.append(String.format("  { prop: '%s', label: '%s'", field.name, field.remark));
            if(field.dictCode != null){
                baseColumns.append(String.format(", columnType: 'dict', dict: '%s'", field.dictCode));
            }
            if(field.isTime){
                minWidth = 180;
            }
            if(field.length > 100){
//                minWidth = 200;
            }
            if(minWidth != null){
                baseColumns.append(String.format(", minWidth: %s", minWidth));
            }
            if("switch".equals(field.formType)){
                baseColumns.append(String.format(", columnType: 'dict', dict: 'yn'"));
            }
            if(field.isOrder){
                baseColumns.append(String.format(", sortable: 'custom'"));
            }
            baseColumns.append(" },\n");
        }
    }

    private static void addFormItems() {
        formItems = new StringBuilder();
        for (MyField field : fields) {
            if(field.isSkip) continue;
            formItems.append(String.format("  { prop: '%s', label: '%s'", field.name, field.remark));
            formItems.append(String.format(", type: '%s'", getFormType(field)));
            if(field.isString){
                formItems.append(", maxlength: ").append(field.length + "");
            }
            if(field.dictCode != null){
                formItems.append(String.format(", dict: '%s'", field.dictCode));
            }
            if("switch".equals(field.formType)){
                formItems.append(", dict: 'yn'");
            }
            if(field.searchType.size() > 0 && !"radio".equals(field.formType)){
                for (String searchType : field.searchType) {
                    formItems.append(String.format(", queryType: '%s'", getQueryType(searchType)));
                }
            }
            if(idName != null && field.name.equals(idName)){
                formItems.append(", readonly: true");
            }
            formItems.append(" },\n");
        }
    }

    private static String getQueryType(String searchType) {
        return switch (searchType){
            case "like" -> "__Like";
            case "likeL" -> "__LikeL";
            case "time" -> "__daterange";
            default -> "__InList";
        };
    }
    private static String getFormType(MyField field) {
        if(field.formType != null){
            return field.formType;
        }else if(field.dictCode != null){
            return "select";
        }else if(field.searchType != null){
            if("time".equals(field.searchType)){
                return "date";
            }else{
                return "input";
            }
        }else if(field.isNumber){
            return "number";

        } else return "input";
    }


    private static void addElFormItems() {
        elFormExpandItems = new StringBuilder();
        elFormBaseItems = new StringBuilder();
        watchParams = new StringBuilder();
        // 时间字段放到后面
        StringBuilder timeSb = new StringBuilder();
        String str;
        for (MyField field : fields) {
            if(field.isSkip) continue;
            if(field.dictCode != null){

                String ifExpand = "";
                if(field.searchType != null && field.searchType.size() > 0){
                    // list , list-radio
                    String multiple = field.searchType.contains("list") ? "multiple" : "";
                    str = String.format(
                            """
                              <el-form-item label="%s" prop="%s" v-if="ifExpand && has('%s')">
                                <el-select v-model="form.%s" style="width: 100%%" clearable %s placeholder="请选择%s">
                                  <el-option v-for="item in dict.%s" :label="item.dictLabel" :value="item.dictValue" :key="item.dictDtlId" />
                                </el-select>
                              </el-form-item>
                            """, field.remark, field.searchName, field.searchName, field.searchName, multiple, field.remark, field.dictCode);
                    elFormExpandItems.append(str);
                    ifExpand = "!ifExpand && ";
                }

                if ("radio".equals(field.formType)) {
                    str = String.format(
                            """
                              <el-form-item label="%s" prop="%s" v-if="%shas('%s')">
                                <el-radio-group v-model="form.%s" clearable >
                                  <el-radio-button v-for="item in dict.%s" :label="item.dictLabel" :value="item.dictValue" :key="item.dictDtlId" />
                                </el-radio-group>
                              </el-form-item>
                            """, field.remark, field.name, ifExpand, field.name, field.name, field.dictCode);
                    elFormBaseItems.append(str);
                } else {
                    str = String.format(
                            """
                              <el-form-item label="%s" prop="%s" v-if="%shas('%s')">
                                <el-select v-model="form.%s" style="width: 100%%" clearable placeholder="请选择%s">
                                  <el-option v-for="item in dict.%s" :label="item.dictLabel" :value="item.dictValue" :key="item.dictDtlId" />
                                </el-select>
                              </el-form-item>
                            """, field.remark, field.name, ifExpand, field.name, field.name, field.remark, field.dictCode);
                    elFormBaseItems.append(str);
                }
                String str2 = String.format(
                        """
                            newVal.%s = newVal.%s?.toString();
                        """, field.name, field.name);
                watchParams.append(str2);
            }else if(field.isTime){
                if(!field.searchType.contains("time")) continue;
                str = String.format(
                    """
                      <el-form-item label="%s" prop="%s" v-if="ifExpand && has('%s')" class="search-time">
                        <el-date-picker v-model="form.%s" value-format="YYYY-MM-DD" style="width: 100%%" type="daterange"
                          range-separator="-" start-placeholder="开始时间" end-placeholder="结束时间" />
                      </el-form-item>
                    """, field.remark, field.name, field.name, field.name);
                timeSb.append(str);
            } else if("switch".equals(field.formType)){
                str = String.format(
                        """
                          <el-form-item label="%s" prop="%s" v-if="has('%s')">
                            <el-switch v-model="form.%s" inline-prompt active-text="是" inactive-text="否" />
                          </el-form-item>
                        """, field.remark, field.name, field.name, field.name);
                elFormBaseItems.append(str);
            }else{
                if(field.name.equals(idName)){
                    continue;
                }
                String type;
                if(field.isNumber){
                    type = "type=\"number\" ";
                }else if("textarea".equals(field.formType)){
                    type = "type=\"textarea\" show-word-limit maxlength=\"" + field.length + "\" ";
                } else{
                    type = field.length != Integer.MAX_VALUE ? "maxlength=\"" + field.length + "\" " : "";
                }
                String ifExpand = "";
                if(field.searchType.stream().anyMatch(item -> item.contains("like")) || "textarea".equals(field.formType)){
                    str = String.format(
                            """
                              <el-form-item label="%s" prop="%s" v-if="ifExpand && has('%s')">
                                <el-input v-model="form.%s" placeholder="请输入%s" clearable />
                              </el-form-item>
                            """, field.remark, field.searchName, field.searchName, field.searchName, field.remark);
                    elFormExpandItems.append(str);
                    ifExpand = "!ifExpand && ";
                }
                str = String.format(
                        """
                          <el-form-item label="%s" prop="%s" v-if="%shas('%s')">
                            <el-input %sv-model="form.%s" placeholder="请输入%s" clearable />
                          </el-form-item>
                        """, field.remark, field.name, ifExpand, field.name, type, field.name, field.remark);
                elFormBaseItems.append(str);
            }
        }
        elFormBaseItems.append(timeSb.toString());
    }

    private static void addTableColumns(){
        tableColumns = new StringBuilder();

        for (MyField field : fields) {
            if(field.isSkip) continue;
            String str = "";
            if(field.dictCode != null){
                str = String.format(
                    """
                      <el-table-column show-overflow-tooltip align="center" min-width="100" prop="%s" label="%s">
                        <template #default="{ row }">
                          <DictText v-bind="getDictDtl(dict.%s, row.%s)" />
                        </template>
                      </el-table-column>
                    """, field.name, field.remark, field.dictCode, field.name);
            }else{
                int width = 100;
                if(field.isTime){
                    width = 180;
                }
                str = String.format(
                    """
                      <el-table-column show-overflow-tooltip align="center" min-width="%d" prop="%s" label="%s" />
                    """, width, field.name, field.remark);
            }
            if("v2".equals(generateVue3)){
                tableColumns.append(str.replace("      ", "        "));
            }else{
                tableColumns.append(str);
            }
        }
    }

    private static void addFormRules(){
        formRules = new StringBuilder();
        for (MyField field : fields) {
            if(field.isSkip) continue;
            if(!field.required) continue;
            formRules.append(String.format(
                    """
                      %s: [{ required: %s, message: "请输入%s", trigger: "blur" }],
                    """, field.name, field.required.toString(), field.remark));
        }
    }

    private static void addFormParams(){
        formParams = new StringBuilder();
        for (MyField field : fields) {
            formParams.append(String.format(
                    """
                      %s: %s,
                    """, field.searchName, field.isNumber ? "null as number | string" : "''"));
        }
    }

    private static void addBaseFormParams(){
        baseFormParams = new StringBuilder();
        for (MyField field : fields) {
            baseFormParams.append(String.format(
                    """
                      %s: %s,
                    """, field.name, field.isNumber ? "null as number | string" : "''"));
        }
    }

    private static void orderByInList(){
        orderByInList = new StringBuilder();
        for (MyField field : fields) {
            if(field.isOrder){
                orderByInList.append(String.format("\t'%s', '%s desc',\n", field.name, field.name));
            }
        }
        orderByInList.append("] as const");
    }

    private static void addDictParams(){
        dictParams = new StringBuilder();
        for (MyField field : fields) {
            if(field.dictCode != null){
                dictParams.append(String.format(
                        """
                          %s: [],
                        """, field.dictCode));
            }
        }
    }

}
